/**
 * this controller will pull the needed information from the DB,
 *  and will build the content of the data to be presented in the GUI.
 *
 * @author Gil Levinson
 * @author Boris Fradlis
 * @author Yogev Levi
 * @author Hila Porat 
 * 
 */
package control;

import java.io.Serializable;
import java.util.Vector;

import system.SystemMode;
import system.SystemTypes;
import system.VCP;
import vcpClasses.*;

// Start of ReadOnlyDataController ***************************************************

public class ReadOnlyDataController extends AbstractController {

	private SystemTypes sysType;
	private boolean returned = false;
	private String ResultStr = "";
	private String reportType = "";
	
		
	// constructor *********************************************************
	
	/**
	 * constructor for this controller instance
	 * @param sysType - the object we'll control
	 */
	public ReadOnlyDataController(SystemTypes sysType) {
		this.sysType = sysType;
		this.setReturned(false);
	}

	// controller methods *****************************************************
	
	/**
	 * this method will get data type to fetch from the DB, and will prepare it as content to present 
	 * @param myType - the type of data to fetch
	 * @return - the content to present
	 */
	
	
	public SystemTypes getReadOnlyData(SystemTypes myType)
	{
		this.reportType = (String) myType.getObj();
		myType.setSysMode(SystemMode.READ_ONLY_DATA);
		this.setReturned(false);
		boolean flag = this.SendToServer(myType);
		while (!isReturned()){}
		if (!flag)
		{
			switch (this.sysType.getSysMode())
			{
				case DB_CON_ERR:
					this.sysType.setObj("Couln't operate the request against the DB!");
					break;
				case EMPTY_RES:
					this.sysType.setObj("There was no data in the requested table!!");
					break;
			}
			return this.sysType;
		}
		else
		{
			this.setReturned(false);
			this.setTitleByReportType();
			this.setReturned(false);
			switch (reportType)
			{
				case "Orders":
					this.updateOrdersContent();
					break;
				case "Reports":
					this.updateReportsContent();
					break;
				case "Workers":
					this.updateWorkersContent();
					break;
				case "Clients":
					this.updateClientsContent();
					break;
				case "Subscribed clients":
					this.updateSubscribedClientsContent();
					break;
				case "Vehicles":
					this.updateVehiclesContent();
					break;
				case "Parking lots":
					this.updateLotsContent();
					break;
			}
			while (!isReturned()){}
			this.sysType.setObj(ResultStr);
			this.sysType.setSysMode(SystemMode.OK);
		}		
		return sysType;
	}

	/**
	 * this method will set the title of the content to present by data type
	 */
	public void setTitleByReportType()
	{
		this.ResultStr = "Requested data to fetch was: " + reportType + "\n\n";
		switch (reportType)
		{
			case "Orders":
				this.ResultStr = ResultStr + "OrderNumber\torderDate\torderTime\torderType\texpectedCost\tactualCost\texpectedLeaveTime\torderStatus\tclientNumber\tvehicleNumber\tsidParkingLocation\n";
				break;
			case "Reports":
				this.ResultStr = ResultStr + "reportID\treportType\treportDate\treportTime\n";
				break;
			case "Workers":
				this.ResultStr = ResultStr + "workerNumber\tworkerRole\tworkerAssociation\tUserName\n";
				break;
			case "Clients":
				this.ResultStr = ResultStr + "clientNumber\tclientPhone\tnumberOfVehicles\tclientBalance\tUserName\n";
				break;
			case "Subscribed clients":
				this.ResultStr = ResultStr + "subscriptionNumber\tstartDate\tclientLeaveTime\ttypeOfSubscription\tclientNumber\tvehicleNumber\tlotNumber\tsubscriptionStatus\n";
				break;
			case "Vehicles":
				this.ResultStr = ResultStr + "vehicleNumber\tclientNumber\n";
				break;
			case "Parking lots":
				this.ResultStr = ResultStr + "parkingLotNumber\tlotStatus\tspaceNumber\tadvanceRate\toccasionalRate\thoursForNormal\thoursForRoutineS\thoursForRoutineM\tKioskIP\n";
				break;
		}
		this.setReturned(true);
	}
	
	/**
	 * this method will prepare the content of the type Orders
	 */
	private void updateOrdersContent()
	{
		int i;
		Vector<Order> v = new Vector<Order>();
		v = (Vector<Order>) this.sysType.getObj();
		Order order = new Order();
		for (i=0; i<v.size();i++)
		{
			order = v.get(i);
			ResultStr = ResultStr + order.getOrderNumber() + "\t";
			ResultStr = ResultStr + order.getOrderDate().toString() + "\t";
			ResultStr = ResultStr + order.getOrderTime().toString() + "\t";
			ResultStr = ResultStr + order.getOrderType() + "\t";
			ResultStr = ResultStr + order.getExpectedCost() + "\t";
			ResultStr = ResultStr + order.getActualCost() + "\t";
			ResultStr = ResultStr + order.getExpectedLeaveTime().toString() + "\t";
			ResultStr = ResultStr + order.getOrderStatus() + "\t";
			ResultStr = ResultStr + order.getClientNumber() + "\t";
			ResultStr = ResultStr + order.getVehicleNumber() + "\t";
			ResultStr = ResultStr + order.getSidParkingLocation() + "\n";
		}
		this.setReturned(true);
	}
	
	/**
	 * this method will prepare the content of the type Reports
	 */
	
	private void updateReportsContent()
	{
		int i;
		Vector<Report> v = new Vector<Report>();
		v = (Vector<Report>) this.sysType.getObj();
		Report report = new Report();
		for (i=0; i<v.size();i++)
		{
			report = v.get(i);
			ResultStr = ResultStr + report.getRid() + "\t";
			ResultStr = ResultStr + report.getType() + "\t";
			ResultStr = ResultStr + report.getDate() + "\t";
			ResultStr = ResultStr + report.getTime() + "\n";
		}
		this.setReturned(true);
	}
	
	/**
	 * this method will prepare the content of the type Workers
	 */
	
	private void updateWorkersContent()
	{
		int i;
		Vector<Worker> v = new Vector<Worker>();
		v = (Vector<Worker>) this.sysType.getObj();
		Worker worker = new Worker();
		for (i=0; i<v.size();i++)
		{
			worker = v.get(i);
			this.ResultStr = ResultStr + worker.getWorkerNumber() + "\t";
			this.ResultStr = ResultStr + worker.getWorkerRole() + "\t";
			this.ResultStr = ResultStr + worker.getWorkerAssociation() + "\t";
			this.ResultStr = ResultStr + worker.getUserName() + "\n";
		}
		this.setReturned(true);
	}
	
	/**
	 * this method will prepare the content of the type clients
	 */
	
	private void updateClientsContent()
	{
		int i;
		Vector<Client> v = new Vector<Client>();
		v = (Vector<Client>) this.sysType.getObj();
		Client client = new Client();
		for (i=0;i<v.size();i++)
		{
			client = v.get(i);
			this.ResultStr = ResultStr + client.getClientNumber() + "\t";
			this.ResultStr = ResultStr + client.getClientPhone() + "\t";
			this.ResultStr = ResultStr + client.getNumberOfVehicles() + "\t";
			this.ResultStr = ResultStr + client.getClientBalance() + "\t";
			this.ResultStr = ResultStr + client.getUserName() + "\n";
		}
		this.setReturned(true);
	}

	/**
	 * this method will prepare the content of the type Subscribed Clients
	 */
	
	private void updateSubscribedClientsContent()
	{
		int i;
		Vector<SubscribedClient> v = new Vector<SubscribedClient>();
		v = (Vector<SubscribedClient>) this.sysType.getObj();
		SubscribedClient client = new SubscribedClient();
		for (i=0;i<v.size();i++)
		{
			client = v.get(i);
			this.ResultStr = ResultStr + client.getSubscriptionNumber() + "\t";
			this.ResultStr = ResultStr + client.getStartDate().toString() + "\t";
			this.ResultStr = ResultStr + client.getClientLeaveTime().toString() + "\t";
			this.ResultStr = ResultStr + client.getTypeOfSubscription() + "\t";
			this.ResultStr = ResultStr + client.getClientNumber() + "\t";
			this.ResultStr = ResultStr + client.getVehicleNumber() + "\t";
			this.ResultStr = ResultStr + client.getLotNumber() + "\t";
			this.ResultStr = ResultStr + client.getTypeOfSubscription() + "\t";
			this.ResultStr = ResultStr + client.getSubscriptionStatus() + "\n";
		}
		this.setReturned(true);
	}
	
	/**
	 * this method will prepare the content of the type Vehicles
	 */
	
	private void updateVehiclesContent()
	{
		int i;
		Vector<Vehicle> v = new Vector<Vehicle>();
		v = (Vector<Vehicle>) this.sysType.getObj();
		Vehicle vehicle = new Vehicle();
		for (i=0; i<v.size();i++)
		{
			vehicle = v.get(i);
			ResultStr = ResultStr + vehicle.getVehicleNumber() + "\t";
			ResultStr = ResultStr + vehicle.getClientNumber() + "\n";
		}
		this.setReturned(true);
	}
	
	/**
	 * this method will prepare the content of the type Parking Lots
	 */
	
	private void updateLotsContent()
	{
		int i;
		Vector<ParkingLot> v = new Vector<ParkingLot>();
		ParkingLot lot = new ParkingLot();
		for (i=0; i<v.size(); i++)
		{
			lot = v.get(i);
			ResultStr = ResultStr + lot.getParkingLotNumber() + "\t";
			ResultStr = ResultStr + lot.getLotStatus() + "\t";
			ResultStr = ResultStr + lot.getNumOfSpacesInRow() + "\t";
			ResultStr = ResultStr + lot.getAdvanceRate() + "\t";
			ResultStr = ResultStr + lot.getOccasionalRate() + "\t";
			ResultStr = ResultStr + lot.getHoursForNormal() + "\t";
			ResultStr = ResultStr + lot.getHoursForRoutineS() + "\t";
			ResultStr = ResultStr + lot.getHoursForRoutineM() + "\t";
			ResultStr = ResultStr + lot.getKioskIP() + "\n";
		}
		this.setReturned(true);
	}
	
	
	
	@Override
 	public boolean SendToServer(Serializable obj) {
		VCP.client.send(obj);
		sysType = (SystemTypes) VCP.client.getResult();
		if (sysType.getSysMode() != SystemMode.OK)
		{
			setReturned(true);
			return false;
		}
		setReturned(true);
		return true;
	}
	
	// Getters and Setters ****************************************************

	/**
	 * @return the returned
	 */
	public boolean isReturned() {
		return returned;
	}

	/**
	 * @param returned the returned to set
	 */
	public void setReturned(boolean returned) {
		this.returned = returned;
	}

	/**
	 * @return the resultStr
	 */
	public String getResultStr() {
		return ResultStr;
	}

	/**
	 * @param resultStr the resultStr to set
	 */
	public void setResultStr(String resultStr) {
		ResultStr = resultStr;
	}

	/**
	 * @return the reportType
	 */
	public String getReportType() {
		return reportType;
	}

	/**
	 * @param reportType the reportType to set
	 */
	public void setReportType(String reportType) {
		this.reportType = reportType;
	}
	
	

}
